package com.example.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.example.common.enums.LikesModuleEnum;
import com.example.common.enums.RoleEnum;
import com.example.utils.SensitiveWordFilter;
import com.example.entity.*;
import com.example.exception.CustomException;
import com.example.mapper.BlogMapper;
import com.example.utils.TokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.example.common.enums.ResultCodeEnum;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 博客信息业务处理
 **/
@Service
public class BlogService {

    @Resource
    private BlogMapper blogMapper;

    @Resource
    private UserService userService;

    @Resource
    private LikesService likesService;

    @Resource
    private CollectService collectService;

    @Resource
    private SensitiveWordService sensitiveWordService;

    // 新增敏感词过滤器实例
    private SensitiveWordFilter sensitiveWordFilter;

    @PostConstruct
    public void initFilter() {
        List<String> words = sensitiveWordService.getSensitiveWords();
        this.sensitiveWordFilter = new SensitiveWordFilter(words);
    }

    /**
     * 新增（添加敏感词过滤）
     */
    public void add(Blog blog) {
        // 敏感词过滤
        blog.setTitle(sensitiveWordFilter.filter(blog.getTitle()));
        blog.setContent(sensitiveWordFilter.filter(blog.getContent()));
        blog.setDescr(sensitiveWordFilter.filter(blog.getDescr()));

        blog.setDate(DateUtil.today());
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.USER.name().equals(currentUser.getRole())){
            blog.setUserId(currentUser.getId());
        }
        blogMapper.insert(blog);
    }

    /**
     * 删除
     */
    public void deleteById(Integer id) {
        blogMapper.deleteById(id);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        for (Integer id : ids) {
            blogMapper.deleteById(id);
        }
    }

    /**
     * 修改
     */
    public void updateById(Blog blog) {
        blogMapper.updateById(blog);
    }


    /**
     * 根据ID查询
     */
    public Blog selectById(Integer id) {
        Blog blog = blogMapper.selectById(id);
        User user = userService.selectById(blog.getUserId());
        List<Blog> userBlogList = blogMapper.selectUserBlog(user.getId());
        user.setBlogCount(userBlogList.size());
        //  当前用户收到的点赞和收藏的数据
        int userLikesCount = 0;
        int userCollectCount = 0;
        for (Blog b : userBlogList) {
            Integer fid = b.getId();
            int likesCount = likesService.selectByFidAndModule(fid, LikesModuleEnum.BLOG.getValue());
            userLikesCount += likesCount;

            int collectCount = collectService.selectByFidAndModule(fid, LikesModuleEnum.BLOG.getValue());
            userCollectCount += collectCount;
        }
        user.setLikesCount(userLikesCount);
        user.setCollectCount(userCollectCount);


        blog.setUser(user);  // 设置作者信息
        // 查询当前博客的点赞数据
        int likesCount = likesService.selectByFidAndModule(id, LikesModuleEnum.BLOG.getValue());
        blog.setLikesCount(likesCount);
        Likes userLikes = likesService.selectUserLikes(id, LikesModuleEnum.BLOG.getValue());
        blog.setUserLike(userLikes != null);

        // 查询当前博客的收藏数据
        int collectCount = collectService.selectByFidAndModule(id, LikesModuleEnum.BLOG.getValue());
        blog.setCollectCount(collectCount);
        Collect userCollect = collectService.selectUserCollect(id, LikesModuleEnum.BLOG.getValue());
        blog.setUserCollect(userCollect != null);

        // 更新博客浏览数据
        blog.setReadCount(blog.getReadCount() + 1);
        this.updateById(blog);
        return blog;
    }


    /**
     * 查询所有
     */

    public List<Blog> selectAll(Blog blog) {
        // 获取当前用户信息
        Account currentUser = TokenUtils.getCurrentUser();
        if (currentUser != null) {
            blog.setRole(currentUser.getRole()); // 设置角色字段
        }
        return blogMapper.selectAll(blog);
    }

    /**
     * 分页查询
     */
    public PageInfo<Blog> selectPage(Blog blog, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Blog> list = blogMapper.selectAll2(blog);
        for (Blog b : list){
            int likesCount = likesService.selectByFidAndModule(b.getId(), LikesModuleEnum.BLOG.getValue());
            b.setLikesCount(likesCount);
        }
        return PageInfo.of(list);
    }


    
    public PageInfo<Blog> selectPage1(Blog blog, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Blog> list = blogMapper.selectAll(blog);
        for (Blog b : list){
            int likesCount = likesService.selectByFidAndModule(b.getId(), LikesModuleEnum.BLOG.getValue());
            b.setLikesCount(likesCount);
        }
        return PageInfo.of(list);
    }


    public List<Blog> selectTop() {
        // 调用 selectAll1 方法查询所有博客数据，传入 null 表示不带查询条件
        List<Blog> blogList = this.selectAll1(null);
        // 使用 Java 8 的 Stream API 对博客列表进行处理
        blogList = blogList.stream()
                // 按照阅读量（readCount）进行降序排序
                .sorted((b1, b2) -> b2.getReadCount().compareTo(b1.getReadCount()))
                // 限制结果数量为前 20 篇博客
                .limit(20)
                // 收集结果为一个新的 List
                .collect(Collectors.toList());
        // 返回处理后的博客列表
        return blogList;
    }

    public List<Blog> selectAll1(Blog blog) {
        return blogMapper.selectAll1(blog);
    }


    public Set<Blog> selectRecommend(Integer blogId) {
        // 获取当前用户信息
        Account currentUser = TokenUtils.getCurrentUser();
        if (currentUser == null) {
            return new HashSet<>();
        }

        // 获取当前用户点赞和收藏的博客 ID 列表
        List<Integer> userLikedBlogIds = likesService.selectUserLikedBlogIds(currentUser.getId(), LikesModuleEnum.BLOG.getValue());
        List<Integer> userCollectedBlogIds = collectService.selectUserCollectedBlogIds(currentUser.getId(), LikesModuleEnum.BLOG.getValue());
        Set<Integer> userInterestedBlogIds = new HashSet<>();
        userInterestedBlogIds.addAll(userLikedBlogIds);
        userInterestedBlogIds.addAll(userCollectedBlogIds);

        // 获取其他用户点赞和收藏的博客 ID 列表
        Map<Integer, Set<Integer>> otherUserInterestedBlogIdsMap = new HashMap<>();
        // 这里简单假设可以通过 likesService 和 collectService 获取其他用户的信息
        List<User> otherUsers = userService.selectAllUsersExceptCurrent(currentUser.getId());
        for (User otherUser : otherUsers) {
            List<Integer> otherUserLikedBlogIds = likesService.selectUserLikedBlogIds(otherUser.getId(), LikesModuleEnum.BLOG.getValue());
            List<Integer> otherUserCollectedBlogIds = collectService.selectUserCollectedBlogIds(otherUser.getId(), LikesModuleEnum.BLOG.getValue());
            Set<Integer> otherUserInterestedBlogIds = new HashSet<>();
            otherUserInterestedBlogIds.addAll(otherUserLikedBlogIds);
            otherUserInterestedBlogIds.addAll(otherUserCollectedBlogIds);
            otherUserInterestedBlogIdsMap.put(otherUser.getId(), otherUserInterestedBlogIds);
        }

        // 计算用户之间的相似度（简单使用交集大小作为相似度）
        Map<Integer, Integer> userSimilarityMap = new HashMap<>();
        for (Map.Entry<Integer, Set<Integer>> entry : otherUserInterestedBlogIdsMap.entrySet()) {
            int otherUserId = entry.getKey();
            Set<Integer> otherUserInterestedBlogIds = entry.getValue();
            int similarity = CollectionUtil.intersection(userInterestedBlogIds, otherUserInterestedBlogIds).size();
            userSimilarityMap.put(otherUserId, similarity);
        }

        // 找到相似度最高的前几个用户
        List<Map.Entry<Integer, Integer>> sortedUserSimilarityList = new ArrayList<>(userSimilarityMap.entrySet());
        sortedUserSimilarityList.sort((e1, e2) -> e2.getValue().compareTo(e1.getValue()));
        List<Integer> topSimilarUserIds = sortedUserSimilarityList.stream()
                .limit(5)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        // 从相似度最高的用户中获取推荐博客
        Set<Integer> recommendedBlogIds = new HashSet<>();
        for (Integer similarUserId : topSimilarUserIds) {
            Set<Integer> similarUserInterestedBlogIds = otherUserInterestedBlogIdsMap.get(similarUserId);
            recommendedBlogIds.addAll(similarUserInterestedBlogIds);
        }
        recommendedBlogIds.removeAll(userInterestedBlogIds); // 去除当前用户已经感兴趣的博客

        // 查询推荐博客信息
        Set<Blog> blogSet = new HashSet<>();
        for (Integer recommendedBlogId : recommendedBlogIds) {
            Blog blog = blogMapper.selectById(recommendedBlogId);
            if (blog != null) {
                int likesCount = likesService.selectByFidAndModule(recommendedBlogId, LikesModuleEnum.BLOG.getValue());
                blog.setLikesCount(likesCount);
                blogSet.add(blog);
            }
        }

        // 限制推荐博客数量为 5 条
        blogSet = blogSet.stream().limit(5).collect(Collectors.toSet());

        return blogSet;
    }

    public void updateReadCount(Integer blogId) {
        blogMapper.updateReadCount(blogId);
    }

    public PageInfo<Blog> selectUser(Blog blog, Integer pageNum, Integer pageSize) {
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.USER.name().equals(currentUser.getRole())){
            blog.setUserId(currentUser.getId());
        }
        return this.selectPage1(blog,pageNum,pageSize);
    }



    public PageInfo<Blog> selectLike(Blog blog, Integer pageNum, Integer pageSize) {
        // 获取当前登录用户信息
        Account currentUser = TokenUtils.getCurrentUser();
        // 如果当前用户角色是普通用户（USER），则将查询条件的 userId 设置为当前用户的 ID
        if (RoleEnum.USER.name().equals(currentUser.getRole())) {
            blog.setUserId(currentUser.getId());
        }
        // 使用 PageHelper 开启分页功能，设置当前页码和每页显示的记录数
        PageHelper.startPage(pageNum, pageSize);
        // 调用 Mapper 方法查询博客数据
        List<Blog> list = blogMapper.selectLike(blog);
        // 将查询结果封装为 PageInfo 对象
        PageInfo<Blog> pageInfo = PageInfo.of(list);
        // 获取分页结果中的博客列表
        List<Blog> blogList = pageInfo.getList();
        // 遍历博客列表，为每篇博客统计点赞数
        for (Blog b : blogList) {
            // 调用 likesService 查询当前博客的点赞数
            int likesCount = likesService.selectByFidAndModule(b.getId(), LikesModuleEnum.BLOG.getValue());
            // 将点赞数设置到博客对象中
            b.setLikesCount(likesCount);
        }
        // 返回封装后的分页信息
        return pageInfo;
    }


    public PageInfo<Blog> selectCollect(Blog blog, Integer pageNum, Integer pageSize) {
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.USER.name().equals(currentUser.getRole())) {
            blog.setUserId(currentUser.getId());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Blog> list = blogMapper.selectCollect(blog);
        PageInfo<Blog> pageInfo = PageInfo.of(list);
        List<Blog> blogList = pageInfo.getList();
        for (Blog b : blogList) {
            int likesCount = likesService.selectByFidAndModule(b.getId(), LikesModuleEnum.BLOG.getValue());
            b.setLikesCount(likesCount);
        }
        return pageInfo;
    }

    public PageInfo<Blog> selectComment(Blog blog, Integer pageNum, Integer pageSize) {
        Account currentUser = TokenUtils.getCurrentUser();
        if (RoleEnum.USER.name().equals(currentUser.getRole())) {
            blog.setUserId(currentUser.getId());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<Blog> list = blogMapper.selectComment(blog);
        PageInfo<Blog> pageInfo = PageInfo.of(list);
        List<Blog> blogList = pageInfo.getList();
        for (Blog b : blogList) {
            int likesCount = likesService.selectByFidAndModule(b.getId(), LikesModuleEnum.BLOG.getValue());
            b.setLikesCount(likesCount);
        }
        return pageInfo;
    }



    public void updateStatus(Integer id, Integer status) {
        Blog blog = blogMapper.selectById(id);
        if (blog == null) {
            throw new CustomException(ResultCodeEnum.BLOG_NOT_FOUND);
        }
        if (!Arrays.asList(0, 1, 2).contains(status)) {
            throw new CustomException(ResultCodeEnum.ILLEGAL_BLOG_STATUS);
        }
        blog.setStatus(status);
        blogMapper.updateById(blog);
    }


}